
#include "io.h"
#include "print.h"
#include "timer.h"
#include "interrupt.h"
#include "thread.h"
#include "debug.h"

#define TIMER0_IRQ  0x20
#define TIMER0_PORT 0x40
#define TIMER0_CTR_PORT  0x43
#define TIMER0_SEL  0
#define TIMER0_MODE 2
#define TIMER0_RWL  3
#define TIMER0_HZ   100
//Timer0 input CLK 119310HZ
#define CLK_HZ 1193180
#define TIMER0_COUNTER_VALUE CLK_HZ/TIMER0_HZ
#define MS2TICKS(ms) (ms/10)
uint32_t ticks;

//timer0 interrupt handler when cpu go here the interrput is disable
static void intr_timer_handler(uint8_t vec_no UNUSED){
	task_tcb* curr;
	ticks++;
	curr=current_thread();
	ASSERT(curr->stack_magic==STACK_MAGIC);
	if(curr->tick==0){
		schedule();
	}else{
		curr->tick--;
	}
}

static void set_timer(uint8_t sel,uint8_t mode,uint8_t rwl,uint16_t hz){
	uint8_t ctrl=0;
	ctrl=(mode<<1)|(rwl<<4)|(sel<<6);
	//set timer0 mode
	outb(ctrl,TIMER0_CTR_PORT);
	//set timer0 init value
	outb((uint8_t)(hz&0xff),TIMER0_PORT);
	outb((uint8_t)(hz>>8&0xff),TIMER0_PORT);
}

void init_timer(void){
	set_timer(TIMER0_SEL,TIMER0_MODE,TIMER0_RWL,TIMER0_COUNTER_VALUE);
	register_intr_handler(TIMER0_IRQ,(intr_handler)intr_timer_handler);
	put_str("timer init done\n");
}

void msleep(uint32_t millisecond){
	uint32_t endticks=ticks+MS2TICKS(millisecond);
	while(ticks<endticks){
		thread_yield();
	}
}
